package com.zx.crowdfunding.mvc.handler;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.zx.crowdfunding.entity.Auth;
import com.zx.crowdfunding.entity.Role;
import com.zx.crowdfunding.global.CrowdFundingGlobal;
import com.zx.crowdfunding.service.api.AdminService;
import com.zx.crowdfunding.service.api.AuthService;
import com.zx.crowdfunding.service.api.MenuService;
import com.zx.crowdfunding.service.api.OperationService;
import com.zx.crowdfunding.service.api.RoleService;
import com.zx.crowdfunding.service.api.SessionService;
import com.zx.crowdfunding.util.ResultEntity;

/**
 * 权限分配 - Handler
 * @author 郑雪
 * @date 2021-12-11
 */
@Controller
public class AssignHandler {

	/**
	 * 管理员Service接口
	 */
	@Autowired
	private AdminService adminService;
	
	/**
	 * 角色Service接口
	 */
	@Autowired
	private RoleService roleService;
	
	/**
	 * 菜单Service接口
	 */
	@Autowired
	private MenuService menuService;
	
	/**
	 * 操作Service接口
	 */
	@Autowired
	private OperationService operationService;
	
	/**
	 * 权限Service接口
	 */
	@Autowired
	private AuthService authService;
	
	/**
	 * 会话Service接口
	 */
	@Autowired
	private SessionService sessionService;
	
	/**
	 * 跳转到管理员分配角色页面
	 * @param adminId 管理员id
	 * @param modelMap 视图携带参数
	 * @return 跳转到管理员分配角色页面
	 */
	@RequestMapping("/assign/to/assign/role/page.html")
	public String toAssignRolePage(
				@RequestParam("adminId") Integer adminId, 
				ModelMap modelMap
			){
		
		// 1.查询已分配的角色
		List<Role> assignedRoleList = roleService.getAssignedRole(adminId);
		
		// 2.查询未分配的角色
		List<Role> unassignedRoleList = roleService.getUnAssignedRole(adminId);
		
		// 3.存入模型
		modelMap.addAttribute("assignedRoleList", assignedRoleList);
		modelMap.addAttribute("unassignedRoleList", unassignedRoleList);
		
		// 4.跳转到管理员分配角色页面
		return "assign-role";
	}
	
	/**
	 * 保存管理员角色关系
	 * @param adminId 管理员id
	 * @param roleIdList 角色id的List集合
	 * @param pageNum 当前页页码
	 * @param keyword 当前查询的关键字
	 * @return 重定向到管理员分页列表页
	 */
	@RequestMapping("/assign/do/role/assign.html")
	public String saveAdminRoleRelationship(
				@RequestParam("adminId") Integer adminId, 
				@RequestParam(value="roleIdList", required=false) List<Integer> roleIdList, 
				@RequestParam("pageNum") Integer pageNum, 
				@RequestParam("keyword") String keyword,
				RedirectAttributes redirectAttributes
			){
		
		// 1.添加管理员角色关系
		adminService.saveAdminRoleRelationship(adminId, roleIdList);
		
		// 2.准备重定向参数
		redirectAttributes.addAttribute("pageNum", pageNum);
		redirectAttributes.addAttribute("keyword", keyword);
		
		// 更新在线用户的菜单集合
		sessionService.editSessionForMenuSet();
		
		// 更新在线用户的权限集合
		sessionService.editSessionForAuth();
				
		// 3.跳转到管理员分页列表页
		return "redirect:/admin/get/page.html";
	}
	
	/**
	 * 查询角色分配权限树形结构
	 * @param roleId 角色id
	 * @return JSON数据
	 */
	@RequestMapping("/assign/get/assign/auth/tree.json")
	@ResponseBody
	public ResultEntity<List<Auth>> getAssignAuthTree(
				@RequestParam("roleId") Integer roleId
			){
		
		// 1.查询全部权限
		List<Auth> allAuthList = authService.getAll();
		
		// 2.声明一个Map，key是Auth对象的id，value是Auth对象
		Map<Integer, Auth> authMap = new HashMap<>();
		
		// 3.遍历全部权限
		for (Auth auth : allAuthList) {
			
			// 4.给authMap添加key和value
			authMap.put(auth.getId(), auth);
			
			// 打开权限
			auth.setOpen(true);
		}
				
		// 5.判断全部权限是否为空
		if(allAuthList != null && allAuthList.size()>0){
			
			// 6.查询已分配的权限
			List<Auth> assignedAuthList = authService.getRoleAssignedAuth(roleId);
			
			// 7.遍历已分配的权限
			for (Auth auth : assignedAuthList) {
				
				// 8.设置为选中
				authMap.get(auth.getId()).setChecked(true);
			}
		}

		// 9.返回JSON数据
		return ResultEntity.successWithData(allAuthList);
	}
	
	/**
	 * 保存角色与权限的关联关系
	 * @param roleId 角色id
	 * @param authIdList 权限id的List集合
	 * @return JSON数据
	 */
	@RequestMapping("/assign/do/auth/assign.json")
	@ResponseBody
	public ResultEntity<String> saveRoleAuthRelationship(
				@RequestParam("roleId") Integer roleId, 
				@RequestParam(value="authIdList", required=false) List<Integer> authIdList
			){
		
		// 添加角色与权限的关联关系
		roleService.saveRoleAuthRelationship(roleId, authIdList);
		
		// 更新在线用户的菜单集合
		sessionService.editSessionForMenuSet();
		
		// 更新在线用户的权限集合
		sessionService.editSessionForAuth();
		
		// 返回JSON数据
		return ResultEntity.successWithoutData();
	}
	
	/**
	 * 查询菜单分配权限树形结构
	 * @param menuId 菜单id
	 * @return JSON数据
	 */
	@RequestMapping("/assign/get/menu/assign/auth/tree.json")
	@ResponseBody
	public ResultEntity<List<Auth>> getMenuAssignAuthTree(
				@RequestParam("menuId") Integer menuId
			){
		
		// 1.查询全部权限
		List<Auth> allAuthList = authService.getAll();
		
		// 2.声明一个Map，key是Auth对象的id，value是Auth对象
		Map<Integer, Auth> authMap = new HashMap<>();
		
		// 3.遍历全部权限
		for (Auth auth : allAuthList) {
			
			// 4.给authMap添加key和value
			authMap.put(auth.getId(), auth);
			
			// 打开权限
			auth.setOpen(true);
		}
				
		// 5.判断全部权限是否为空
		if(allAuthList != null && allAuthList.size()>0){
			
			// 6.查询已分配的权限
			List<Auth> assignedAuthList = authService.getMenuAssignedAuth(menuId);
			
			// 7.遍历已分配的权限
			for (Auth auth : assignedAuthList) {
				
				// 8.设置为选中
				authMap.get(auth.getId()).setChecked(true);
			}
		}

		// 9.返回JSON数据
		return ResultEntity.successWithData(allAuthList);
	}
	
	/**
	 * 保存菜单与权限的关联关系
	 * @param menuId 菜单id
	 * @param authIdList 权限id的List集合
	 * @return JSON数据
	 */
	@RequestMapping("/assign/do/menu/auth/assign.json")
	@ResponseBody
	public ResultEntity<String> saveMenuAuthRelationship(
				@RequestParam("menuId") Integer menuId, 
				@RequestParam(value="authIdList", required=false) List<Integer> authIdList
			){
		
		// 添加菜单与权限的关联关系
		menuService.saveMenuAuthRelationship(menuId, authIdList);
		
		// 设置全局静态变量需要更新，为了通知SpringSecurity的权限授权数据源下次使用时需重新加载
		CrowdFundingGlobal.UPDATE_RESOURCE_AUTH = true;
		
		// 更新在线用户的菜单集合
		sessionService.editSessionForMenuSet();
		
		// 返回JSON数据
		return ResultEntity.successWithoutData();
	}
	
	/**
	 * 查询操作分配权限树形结构
	 * @param operationId 操作id
	 * @return JSON数据
	 */
	@RequestMapping("/assign/get/operation/assign/auth/tree.json")
	@ResponseBody
	public ResultEntity<List<Auth>> getOperationAssignAuthTree(
				@RequestParam("operationId") Integer operationId
			){
		
		// 1.查询全部权限
		List<Auth> allAuthList = authService.getAll();
		
		// 2.声明一个Map，key是Auth对象的id，value是Auth对象
		Map<Integer, Auth> authMap = new HashMap<>();
		
		// 3.遍历全部权限
		for (Auth auth : allAuthList) {
			
			// 4.给authMap添加key和value
			authMap.put(auth.getId(), auth);
			
			// 打开权限
			auth.setOpen(true);
		}
				
		// 5.判断全部权限是否为空
		if(allAuthList != null && allAuthList.size()>0){
			
			// 6.查询已分配的权限
			List<Auth> assignedAuthList = authService.getOperationAssignedAuth(operationId);
			
			// 7.遍历已分配的权限
			for (Auth auth : assignedAuthList) {
				
				// 8.设置为选中
				authMap.get(auth.getId()).setChecked(true);
			}
		}

		// 9.返回JSON数据
		return ResultEntity.successWithData(allAuthList);
	}
	
	/**
	 * 保存操作与权限的关联关系
	 * @param operationId 操作id
	 * @param authIdList 权限id的List集合
	 * @return JSON数据
	 */
	@RequestMapping("/assign/do/operation/auth/assign.json")
	@ResponseBody
	public ResultEntity<String> saveOperationAuthRelationship(
				@RequestParam("operationId") Integer operationId, 
				@RequestParam(value="authIdList", required=false) List<Integer> authIdList,
				HttpServletRequest request
			){
		
		// 添加操作与权限的关联关系
		operationService.saveOperationAuthRelationship(operationId, authIdList);
		
		// 获取Servlet上下文
		ServletContext servletContext = request.getSession().getServletContext();
		
		// 更新全局静态变量和Application域中的值
		authService.updateGlobalCodeAuth(servletContext);
		
		// 设置全局静态变量需要更新，为了通知SpringSecurity的权限授权数据源下次使用时需重新加载
		CrowdFundingGlobal.UPDATE_RESOURCE_AUTH = true;
		
		// 返回JSON数据
		return ResultEntity.successWithoutData();
	}
	
}
